#include "threadtimer.h"

static Timer_Thread g_time_thread;

bool add_sink(TimeSink* sink, uint32 ms_second)
{
	return g_time_thread.add_sink(sink,ms_second);
}

bool del_sink(TimeSink* sink)
{
	return g_time_thread.delete_sink(sink);
}

bool add_thread_time(uint32 time)
{
    return g_time_thread.add_time(time);
}

void TSleep(uint32 seconds)
{
	struct timespec ts, rmts;
	
	ts.tv_sec = seconds/1000;
	ts.tv_nsec = (seconds%1000)*1000000;
	while(1)
	{
		int ret = nanosleep(&ts, &rmts);
		if(ret == 0) 
		{
			break;
		}

		int sleepErr = errno;
		if(ret == -1 && sleepErr == EINTR)
		{
			ts = rmts;
		}
	}
}

Timer_Thread::Timer_Thread()
{
	m_log = new logfile("Timer_Thread");
	InitThread(false);
}

Timer_Thread::~Timer_Thread()
{
   delete m_log;
   StopThread();
}

bool  Timer_Thread::add_sink(TimeSink* sink, uint32 ms_second)
{
    m_lock.EnterLock();
	Sink_info node ;
	node.sink = sink;
	node.second = ms_second;
	node.count = 0;

    if(delete_sink(sink) == true)
		m_log->WriteTrace("add sink is error");
	
	m_sink.push_back(node);

	/*char tmp[1024] = {0};
	sprintf(tmp,"addsink,m_sink.size()=%d,this=%u,sink=%x,count=%d",
		m_sink.size(),this,sink,ms_second);
	m_log->WriteTrace(tmp);*/
	
	m_lock.LeaveLock();
	return true;
}

bool  Timer_Thread::delete_sink(TimeSink* sink)
{
	m_lock.EnterLock();
	
	vector<Sink_info>::iterator itr = m_sink.begin();
	while (itr != m_sink.end())
	{
		if(itr->sink == sink)
		{
			/*char tmp[1024] = {0};
			sprintf(tmp,"delsink,m_sink.size()=%d,this=%u,sink=%x,count=%d",
				m_sink.size(),this,itr->sink,itr->count);
			m_log->WriteTrace(tmp);*/

			m_sink.erase(itr);
		    break;
		}	    
		++itr;
	}

	m_lock.LeaveLock();
	return false;

}

void Timer_Thread::Execute()
{
	uint32 time = m_time;
	
    m_log->WriteTrace("Execute");	
	while(!m_finished)
	{
		if(m_time % 2000  == 0)
		{
			char tt[1024] = {0};
			sprintf(tt,"this=%u,m_sink.size=%d,time=%d,m_time=%d",
				this,m_sink.size(),time,m_time);
			m_log->WriteTrace(tt);
		}

        if(time + 10 < m_time)
		{
			m_lock.EnterLock();
			time = m_time;
			vector<Sink_info>::iterator itr = m_sink.begin();

			uint32 i=0;
			while (i < m_sink.size())
			{
				if(itr->second <= itr->count)
				{
				  itr->count = 0;
				  itr->sink->OnTimer();				 
				}
 
				itr->count++;
				itr++;
				i++;
			}

			m_lock.LeaveLock();
		}
		else
		   TSleep(0);
	}
}


